//
// CLastFmPlugin.cpp
// Your copyright notice
//
#include "LastFmPlugin.h"
#include "LastFmUI.h"

#include "LastFmPlugin.rsg"
#include "LastFmPlayer.h"
#include "HandshakeForm.h"
#include "Playlist.h"
#include "PluginUtility.h"

#include <eikenv.h>
#include <bautils.h>

_LIT(KLastFmPlugin, "Last Fm");
_LIT(KLastFmHyphen, " - ");
_LIT(KLastFmSettingsFilename, "C:\\lastfm.set");

enum TPlayerPluginCommandId
{
	EPluginCommandId = 0x6300,
	ELastFmCommandLogin
};

// Construction and destruction functions
CLastFmPlugin* CLastFmPlugin::NewL(TAny* aInitParams)
{
	CLastFmPlugin* self = new(ELeave) CLastFmPlugin(aInitParams);
	CleanupStack::PushL(self);
	self->ConstructL(); 
	CleanupStack::Pop();
	return self;
}

CLastFmPlugin::~CLastFmPlugin()
{
	//Clean objects
	DELETE(iLastFmPlayer);
	DELETE(iLastFmUI);
	DELETE(iScrobblerEngine);

	//Delete resource file
	CCoeEnv::Static()->DeleteResourceFile(iOffset);
}

CLastFmPlugin::CLastFmPlugin(TAny* aInitParams)
:	iInitParams((CPluginInterface::TPluginInterfaceInitParams*)aInitParams), 
	iLastFmPlayer(NULL), iLastFmUI(NULL), iScrobblerEngine(NULL), iPlaylist(NULL), 
	iOnImageReadyCallback(&OnImageIsReady, this), 
	iState(EStateNotReady)
{
}

void CLastFmPlugin::ConstructL()
{
	//Create UI manager
	iLastFmUI = CLastFmUI::NewL();

	//Create scrobbler engine
	iScrobblerEngine = CAudioscrobblerEngine::NewL(*this);

	//Create lastfm player
	iLastFmPlayer = CLastFmPlayer::NewL(*this);

	//Read username
	ReadUsernameL();

	//Add resource file to plugin
	AddResourceFileL();
}

void CLastFmPlugin::AddResourceFileL()
{
	TFileName f;

	//Get rsc filename
#if __WINS__
	f.Append(_L("Z:\\system\\libs\\plugins\\LastFmPlugin.rsc"));

#else
	Dll::FileName(f);

	//Change dll by rsc
	f.Replace(f.Find(_L(".dll")), 4, _L(".rsc"));
#endif

	//Read resource compiled file 
	iOffset = CEikonEnv::Static()->AddResourceFileL(f);
}

const TDesC& CLastFmPlugin::GetMenuText()
{
	return KLastFmPlugin;
}

TInt CLastFmPlugin::GetMenuCommand()
{
	return EPluginCommandId;
}

void CLastFmPlugin::AddExtraMenu(CEikMenuPane* aMenuPane)
{
	//Login
	CPluginUtility::AddMenuItem(ELastFmCommandLogin, ((iUsername.Length() && iPassword.Length()) ? _L("Change account") : _L("Login")), aMenuPane);
}

void CLastFmPlugin::HandleCommandL(TInt aCommand)
{
	switch (aCommand)
	{
	case ELastFmCommandLogin:
		//Login
		LoginL();
		break;
	}
}

void CLastFmPlugin::Draw(CWindowGc& aGc, const TRect& aRect) const
{
	//Draw ui
	iLastFmUI->Draw(aGc, aRect);
}

void CLastFmPlugin::SetContainer(MPluginContainer* aContainer)
{
	CPluginInterface::SetContainer(aContainer);
	iLastFmUI->SetContainer(aContainer);
}

void CLastFmPlugin::Activate()
{
	//Activate ui
	iLastFmUI->Activate();

	//Update ticker text
	iLastFmUI->SetTickerText(iMetadata);
}

void CLastFmPlugin::Deactivate()
{
	//Stop playing
	if (IsReadyToStop()) StopL();

	//Deactivate ui
	iLastFmUI->Deactivate();
}

TRgb CLastFmPlugin::BackBorderColor() const { return iLastFmUI->BackBorderColor(); }
TRgb CLastFmPlugin::BackShadowColor() const { return iLastFmUI->BackShadowColor(); }
TRgb CLastFmPlugin::BackColor() const { return iLastFmUI->BackColor(); }
TRgb CLastFmPlugin::InsideBorderColor() const { return iLastFmUI->InsideBorderColor(); }
TRgb CLastFmPlugin::InsideColor() const { return iLastFmUI->InsideColor(); }
TRgb CLastFmPlugin::ForeColor() const { return iLastFmUI->ForeColor(); }

void CLastFmPlugin::PlayL()
{
	if (!IsReadyToPlay()) return;

	//Stop & Play
	if (IsReadyToStop()) StopL();

	//Set text and icon
	BufferStateChanged(EFalse, -1);

	//Make handshake
	HandshakeL();
}

void CLastFmPlugin::StopL()
{
	//Stop player
	iLastFmPlayer->StopL();

	//Set is buffering
	iLastFmUI->SetIsBuffering(EFalse, -1);

	//Set icon
	iLastFmUI->SetTickerIcon(CLastFmUI::EStop);
	iLastFmUI->SetTickerText(_L("Stopped"));

	iState = EStateReadyToPlay;
}

TBool CLastFmPlugin::IsReadyToPlay() 
{ 
	return (iState == EStateReadyToPlay);
}

TBool CLastFmPlugin::IsReadyToStop()
{
	return (iState == EStatePlaying);
}

TInt CLastFmPlugin::Volume()
{
	return iLastFmPlayer->Volume();
}

void CLastFmPlugin::SetVolume(TInt aVolume)
{
	iLastFmPlayer->SetVolume(aVolume);
}

void CLastFmPlugin::LoginL()
{
	//Display form
	CHandshakeForm* form = CHandshakeForm::NewL(iUsername, iPassword);
	form->ExecuteLD();

	//Check if username is saved
	if (iUsername.Length() == 0 || iPassword.Length() == 0) return;

	//Stop before open new url
	if (IsReadyToStop()) StopL();

	//Play
	iState = EStateReadyToPlay;
	PlayL();
}

void CLastFmPlugin::BufferStateChanged(TBool aIsBuffering, TInt aPercent)
{
	iLastFmUI->SetIsBuffering(aIsBuffering, aPercent);
}

void CLastFmPlugin::Finished()
{
	//Next track
	if (++iCurrentTrack >= iPlaylist->Tracks().Count())
	{
		//We make a new handshake
		HandshakeL();
	}
	else
	{
		//Play track
		PlayCurrentTrackL();		
	}
}

void CLastFmPlugin::HandshakeL()
{
	//Set icon and text
	iLastFmUI->SetTickerIcon(CLastFmUI::EBuffering);
	iLastFmUI->SetTickerText(_L("Authenticating..."));

	//Make handshake
	iScrobblerEngine->RequestPlaylistL(iUsername, iPassword);

	iState = EStateHandshaking;
}

void CLastFmPlugin::PlaylistRequestedL(TPlaylist* aPlaylist)
{
	//Set playlist
	iPlaylist = aPlaylist;

	//Save username
	WriteUsernameL();

	//Check if there are tracks
	if (iPlaylist->Tracks().Count() == 0)
	{
		//No tracks
		iLastFmUI->SetTickerIcon(CLastFmUI::EError);
		iLastFmUI->SetTickerText(_L("No tracks available."));

		iState = EStateReadyToPlay;
		return;
	}

	//Do streaming over first url of selected item
	iCurrentTrack = 0;
	PlayCurrentTrackL();
}

void CLastFmPlugin::RunError(const TDesC& aErrorDesc)
{
	//Set icon and text
	iLastFmUI->SetTickerIcon(CLastFmUI::EError);
	iLastFmUI->SetTickerText(aErrorDesc);

	iState = EStateFailed;
}

void CLastFmPlugin::PlayCurrentTrackL()
{
	TTrack* currentTrack = iPlaylist->Tracks()[iCurrentTrack];

	//Set title
	iLastFmUI->SetTitle(iPlaylist->Title());
	iLastFmUI->SetTickerText(_L("Loading cover ..."));

	if (currentTrack->ImageUrl().Length() > 0)
	{
		//Set image (asynchronous!)
		iLastFmUI->SetImageUrl(currentTrack->ImageUrl(), iOnImageReadyCallback);
	}
	else
	{
		PlayCurrentTrack2L();
	}
}

void CLastFmPlugin::PlayCurrentTrack2L()
{
	TTrack* currentTrack = iPlaylist->Tracks()[iCurrentTrack];

	//Stream current track
	iLastFmPlayer->StartL(currentTrack->Location());
	
	//Build metadata text
	iMetadata.Copy(currentTrack->Title());
	iMetadata.Append(KLastFmHyphen);
	iMetadata.Append(currentTrack->Artist());
	iMetadata.Append(KLastFmHyphen);
	iMetadata.Append(currentTrack->Album());
	iLastFmUI->SetTickerText(iMetadata);

	//Set state playing
	iState = EStatePlaying;
}

void CLastFmPlugin::ReadUsernameL()
{
	RFs fsSession;
	User::LeaveIfError(fsSession.Connect());

	//Check if file exists
	if (!BaflUtils::FileExists(fsSession, KLastFmSettingsFilename)) return;

	//Open file
	RFile file;
	User::LeaveIfError(file.Open(fsSession, KLastFmSettingsFilename, EFileStream|EFileRead));

	//Read username
	HBufC8* data = HBufC8::NewL(255);
	TPtr8 ptr8 = data->Des();
	file.Read(ptr8);

	//Close
	file.Close();
	fsSession.Close();

	//Set username
	TPtr ptr16((TUint16*)data->Ptr(), data->Size() >> 1, data->Size() >> 1);
	iUsername.Copy(ptr16);

	//Clean
	delete data;
	data = NULL;
}

void CLastFmPlugin::WriteUsernameL()
{
	RFs fsSession;
	User::LeaveIfError(fsSession.Connect());

	RFile file;

	//Check if file exists
	if (BaflUtils::FileExists(fsSession, KLastFmSettingsFilename))
	{
		//Delete
		User::LeaveIfError(fsSession.Delete(KLastFmSettingsFilename));
	}

	//Create file
	User::LeaveIfError(file.Create(fsSession, KLastFmSettingsFilename, EFileStream|EFileWrite));
	
	//Write username
	TPtrC8 ptrC8 ((TUint8*)iUsername.Ptr(), iUsername.Size());
	file.Write(ptrC8);

	//Close
	file.Close();
	fsSession.Close();
}

TInt CLastFmPlugin::OnImageIsReady(TAny* aAny)
{
	CLastFmPlugin* self = (CLastFmPlugin*)aAny;
	self->PlayCurrentTrack2L();
}